package com.evolved.automata.android.bots.speechbot;
import com.evolved.automata.*;
import java.util.*;
import java.io.*;
import android.content.*;
import android.database.sqlite.*;

public class StandardTools 
{
	
	public static final Hashtable<Integer, String> MONTH_NUMBER_TO_NAME_MAP;
	public static final Hashtable<Integer, String> DAY_OF_WEEK_NUMBER_TO_NAME_MAP;
	public static final Hashtable<Integer, String> MONTH_NUMBER_TO_SEASON_NAME_MAP;
	
	
	static 
	{
		MONTH_NUMBER_TO_NAME_MAP = new Hashtable<Integer, String>();
		MONTH_NUMBER_TO_NAME_MAP.put(1, "January");
		MONTH_NUMBER_TO_NAME_MAP.put(2, "February");
		MONTH_NUMBER_TO_NAME_MAP.put(3, "March");
		MONTH_NUMBER_TO_NAME_MAP.put(4, "April");
		MONTH_NUMBER_TO_NAME_MAP.put(5, "May");
		MONTH_NUMBER_TO_NAME_MAP.put(6, "June");
		MONTH_NUMBER_TO_NAME_MAP.put(7, "July");
		MONTH_NUMBER_TO_NAME_MAP.put(8, "August");
		MONTH_NUMBER_TO_NAME_MAP.put(9, "September");
		MONTH_NUMBER_TO_NAME_MAP.put(10, "October");
		MONTH_NUMBER_TO_NAME_MAP.put(11, "November");
		MONTH_NUMBER_TO_NAME_MAP.put(12, "December");
		
		
		DAY_OF_WEEK_NUMBER_TO_NAME_MAP = new Hashtable<Integer, String>();
		DAY_OF_WEEK_NUMBER_TO_NAME_MAP.put(1,"Sunday");
		DAY_OF_WEEK_NUMBER_TO_NAME_MAP.put(2,"Monday");
		DAY_OF_WEEK_NUMBER_TO_NAME_MAP.put(3,"Tuesday");
		DAY_OF_WEEK_NUMBER_TO_NAME_MAP.put(4,"Wednesday");
		DAY_OF_WEEK_NUMBER_TO_NAME_MAP.put(5,"Thursday");
		DAY_OF_WEEK_NUMBER_TO_NAME_MAP.put(6,"Friday");
		DAY_OF_WEEK_NUMBER_TO_NAME_MAP.put(7,"Saturday");
		
		MONTH_NUMBER_TO_SEASON_NAME_MAP = new Hashtable<Integer, String>();
		MONTH_NUMBER_TO_SEASON_NAME_MAP.put(1,"Winter");
		MONTH_NUMBER_TO_SEASON_NAME_MAP.put(2,"Winter");
		MONTH_NUMBER_TO_SEASON_NAME_MAP.put(3,"Spring");
		MONTH_NUMBER_TO_SEASON_NAME_MAP.put(4,"Spring");
		MONTH_NUMBER_TO_SEASON_NAME_MAP.put(5,"Spring");
		MONTH_NUMBER_TO_SEASON_NAME_MAP.put(6,"Summer");
		MONTH_NUMBER_TO_SEASON_NAME_MAP.put(7,"Summer");
		MONTH_NUMBER_TO_SEASON_NAME_MAP.put(8,"Summer");
		MONTH_NUMBER_TO_SEASON_NAME_MAP.put(9,"Fall");
		MONTH_NUMBER_TO_SEASON_NAME_MAP.put(10,"Fall");
		MONTH_NUMBER_TO_SEASON_NAME_MAP.put(11,"Winter");
		MONTH_NUMBER_TO_SEASON_NAME_MAP.put(12,"Winter");
	}
	
	
	
	public static void writeToFile(String logFileFullName, String text)
	{
		BufferedWriter writer=null;
		try
		{
			writer= new BufferedWriter(new FileWriter(logFileFullName,true));
			writer.write(text);
			writer.newLine();
		}
		catch (Exception e)
		{
			String s=getCurrentDateString();
		}
		finally
		{
			if (writer!=null)
			{
				try
				{
					writer.close();
				}
				catch (Exception e)
				{
					
				}
			}
		}
	}

	
	public static void mergeKeyValues(Hashtable<String,String> sourceMap, Hashtable<String,String> targetMap)
	{
		for (String sourceKey:sourceMap.keySet().toArray(new String[0]))
		{
			targetMap.put(sourceKey, sourceMap.get(sourceKey));
		}
	}

	public static void transferKeyValues(Hashtable<String,String> sourceMap, Hashtable<String,String> targetMap)
	{
		for (String keyName:sourceMap.keySet().toArray(new String[0]))
		{
			if (targetMap.containsKey(keyName))
				targetMap.put(keyName, sourceMap.get(keyName));
		}
	}
	
	// babyfish
	public static String[] extractQueryList(Hashtable<String, String> keyValueMap)
	{
		LinkedList<String> query = new LinkedList<String>();
		for (String keyname:keyValueMap.keySet().toArray(new String[0]))
		{
			if (keyValueMap.get(keyname).length()==0)
			{
				query.add(keyname);
				keyValueMap.remove(keyname);
			}
		}
		String[] queryList = new String[0];
		if (query.size()>0)
			queryList = query.toArray(new String[0]);
		
		return queryList;
	}
	
	
	public static String serializeToString(String[] serializedWorlds)
	{
		if ((serializedWorlds==null)||(serializedWorlds.length==0))
			return "";
		StringBuilder serializedSet = new StringBuilder(serializedWorlds[0]);
		int i=0;
		String world;
		for (i=1;i<serializedWorlds.length;i++)
		{
			serializedSet.append(InferenceApp.WORLD_SEPARATOR);
			serializedSet.append(serializedWorlds[i]);
		}
		return serializedSet.toString();
	}
	
	public static String[] parseSerializedStringToWorlds(String serializedWorlds)
	{
		String[] worlds = serializedWorlds.split(InferenceApp.WORLD_SEPARATOR);
		return worlds;
	}
	
	public static String serializeToString(Hashtable<String, String> keyValueMap)
	{
		StringBuilder sBuilder = new StringBuilder("");

		String pairFormat="%1$s%2$s%3$s";
		boolean second=false;
		for (String keyName:keyValueMap.keySet().toArray(new String[0]))
		{
			if (second)
			{
				sBuilder.append(InferenceApp.PAIR_SEPARATOR);
			}
			sBuilder.append(String.format(pairFormat, keyName,InferenceApp.KEY_VALUE_SEPARATOR,keyValueMap.get(keyName)));
			second=true;
		}
		return sBuilder.toString();
	}
	
	
	public static String serializeToString(KeyValuePair[] pairs)
	{
		StringBuilder sBuilder = new StringBuilder("");

		String pairFormat="%1$s%2$s%3$s";
		boolean second=false;
		for (KeyValuePair keyValuePair:pairs)
		{
			if (second)
			{
				sBuilder.append(InferenceApp.PAIR_SEPARATOR);
			}
			sBuilder.append(String.format(pairFormat, keyValuePair.GetKey(),InferenceApp.KEY_VALUE_SEPARATOR,keyValuePair.GetValue()));
			second=true;
		}
		return sBuilder.toString();
	}
	
	public static Hashtable<String, String> parseToKeyValueMapFromKeyValuePairs(KeyValuePair[] pairs)
	{
		Hashtable<String, String> keyValueMap = new Hashtable<String, String>();
		
		if (pairs==null)
			return keyValueMap;


		for (KeyValuePair kvPair:pairs)
		{
			keyValueMap.put(kvPair.GetKey(), kvPair.GetValue());
		}
		return keyValueMap;
	}
	
	public static KeyValuePair[] parseToKeyValuePairsFromString(Hashtable<String, String> keyValueMap)
	{
		KeyValuePair[] pairs;
		
		pairs = new KeyValuePair[keyValueMap.size()];
		int index=0;
		for (String keyName:keyValueMap.keySet().toArray(new String[0]))
		{
			pairs[index] = new KeyValuePair(keyName, keyValueMap.get(keyName));
			index++;
		}
		return pairs;
	}
	
	public static KeyValuePair[] parseToKeyValuePairsFromString(String pairString)
	{
		KeyValuePair[] pairs;
		String[] pairArray = pairString.split(InferenceApp.PAIR_SEPARATOR);
		pairs = new KeyValuePair[pairArray.length];
		String[] kvPair;
		int index=0;
		for (String keyValue: pairArray)
		{
			kvPair=keyValue.split(InferenceApp.KEY_VALUE_SEPARATOR);
			if (kvPair.length==1)
				pairs[index]=new KeyValuePair(kvPair[0], "");
			else
				pairs[index]=new KeyValuePair(kvPair[0], kvPair[1]);
			index++;
		}
		return pairs;
	}
	
	public static Hashtable<String,String> parseToKeyValueMap(String pairString)
	{
		Hashtable<String,String> out = new Hashtable<String, String>();
		if (pairString.length()>0)
		{
			KeyValuePair[] pairs = parseToKeyValuePairsFromString(pairString);
			for (KeyValuePair kvPair:pairs)
			{
				out.put(kvPair.GetKey(), kvPair.GetValue());
			}
		}
		return out;
	}
	
	
	public static SQLiteDatabase getDataBase(Context context, String dbName)
	{
		SQLiteDatabase dataBase;
		dataBase = context.openOrCreateDatabase(dbName,Context.MODE_PRIVATE,null);
		dataBase.setLocale(Locale.getDefault());
		dataBase.setLockingEnabled(true);
		dataBase.setVersion(1);
		return dataBase;
	}
	
	public static int getCurrentDateInt()
	{
		Calendar calendar = Calendar.getInstance();
		int yearMultiplier=10^4;
		int monthMultiplier=10^2;
		int year = calendar.get(calendar.YEAR);
		int day = calendar.get(calendar.DAY_OF_MONTH)+1;
		int month = calendar.get(calendar.MONTH);
		int totalDate = year*yearMultiplier+month*monthMultiplier+day;
		return totalDate;
		
	}
	
	public static String mapDatepartToStringName(int datepart, int value)
	{
		switch (datepart)
		{
			case Calendar.DAY_OF_WEEK:
				if (DAY_OF_WEEK_NUMBER_TO_NAME_MAP.containsKey(value))
					return DAY_OF_WEEK_NUMBER_TO_NAME_MAP.get(value);
				else
					return "";
			case Calendar.MONTH:
				if (MONTH_NUMBER_TO_NAME_MAP.containsKey(value))
					return MONTH_NUMBER_TO_NAME_MAP.get(value);
				else
					return "";	
		}
		return "";
	}
	
	// TODO: Make this smarter
//	public static String getSeason(int dateInt)
//	{
//		
//		double base
//	}
	
	public static String getCurrentDateString()
	{
		Calendar calendar = Calendar.getInstance();
		int yearMultiplier=10000;
		int monthMultiplier=100;
		int year = calendar.get(calendar.YEAR);
		int day = calendar.get(calendar.DAY_OF_MONTH);
		int month = calendar.get(calendar.MONTH)+1;
		int totalDate = year*yearMultiplier+month*monthMultiplier+day;
		return ""+totalDate;
		
	}
	
	public static String mapValueToKey(Hashtable<String,String> map, String value)
	{
		String out=null;
		for (String key:map.keySet().toArray(new String[0]))
		{
			if (map.get(key).equals(value))
				return key;
		}
		return out;
	}
	
	public static String escapeDBString(String data)
	{
		if (data==null)
			return "";
		else
			return data.replace((CharSequence)"'", (CharSequence)"''");
	}
	
	public static void sortStack(String[] stack, String[] sortPreferenceOrder, boolean ascendingP)
	{
		if ((sortPreferenceOrder!=null)&&(sortPreferenceOrder.length>0))
			Arrays.sort(stack,new StackComparator<String>(sortPreferenceOrder,ascendingP));
	}
	
	public static int doLogicalStringComparison(java.lang.String string, java.lang.String string2)
	{
		Double lNum=new Double(0),rNum= new Double(0);
		try
		{
			lNum=new Double(string);
			rNum = new Double(string2);
		}
		catch (Exception e)
		{
			return 0;
		}
		return lNum.compareTo(rNum);
	}

	
	public static void writeModelsToCSV(String outputFileFullName, String[] keys, String[] serializedWorlds)
	{
		BufferedWriter writer=null;
		try
		{
			writer = new BufferedWriter(new FileWriter(outputFileFullName));
			writeModelKeysToCSV(writer,keys);
			for (String serializedWorld:serializedWorlds)
			{
				writeModelStructureToCSV(writer,keys,serializedWorld);
			}
		}
		catch (Exception e)
		{
			java.io.StringWriter traceText = new java.io.StringWriter();
			java.io.PrintWriter pWriter = new java.io.PrintWriter(traceText,true);
			e.printStackTrace(pWriter);
			pWriter.close();
			throw new RuntimeException(traceText.toString());
		}
		finally
		{
			if (writer!=null)
			{
				try
				{
					writer.close();
				}
				catch (Exception e)
				{
					
				}
			}
		}
	}
	
	public static void writeModelsToCSV(String outputFileFullName, String[] serializedWorlds)
	{
		HashSet<String> keys = extractAllKeys(serializedWorlds);
		writeModelsToCSV(outputFileFullName,keys.toArray(new String[0]),serializedWorlds);
	}
	
	public static String[] importFromCSV(String inputFileFullName)
	{
		String[] keyList=null;
		LinkedList<String> outputList = new LinkedList<String>();
		BufferedReader reader=null;
		String lineInput;
		boolean keyLine=true;
		String[] valueList;
		Hashtable<String,String> keyValuePairs;
		int totalKeys=0;
		try
		{
			reader = new BufferedReader(new FileReader(inputFileFullName));
			while ((lineInput=reader.readLine())!=null)
			{
				if (keyLine)
				{
					keyLine=false;
					keyList = splitCommaDelimitedString(lineInput,',');
					totalKeys = keyList.length;
				}
				else
				{
					valueList=splitCommaDelimitedString(lineInput,',');
					// TODO: Figure out how to make this more efficient
					keyValuePairs= new Hashtable<String, String>();
					for (int i=0;i<totalKeys;i++)
					{
						if (valueList[i].length()>0)
						{
							keyValuePairs.put(keyList[i].trim(), valueList[i].trim());
						}
					}
					if (keyValuePairs.size()>0)
					{
						outputList.add(serializeToString(keyValuePairs));
					}
					
				}
			}
		}
		catch (Exception e)
		{
			java.io.StringWriter traceText = new java.io.StringWriter();
			java.io.PrintWriter pWriter = new java.io.PrintWriter(traceText,true);
			e.printStackTrace(pWriter);
			pWriter.close();
			throw new RuntimeException(traceText.toString());
		}
		finally
		{
			if (reader!=null)
			{
				try
				{
					reader.close();
				}
				catch (Exception e2)
				{
					
				}
			}
		}
		
		return outputList.toArray(new String[0]);
	}
	
	
	public static HashSet<String> extractAllKeys(String[] serializedWorlds)
	{
		HashSet<String> outerMap = new HashSet<String>();
		Hashtable<String,String> innerMap;
		
		
		for (String serializedWorld:serializedWorlds)
		{
			innerMap = parseToKeyValueMap(serializedWorld);
			for (String key:innerMap.keySet().toArray(new String[0]))
			{
				if (!outerMap.contains(key))
					outerMap.add(key);
			}
		}
		return outerMap;
	}
	
	public static void writeModelKeysToCSV(BufferedWriter writer, String[] keys) throws IOException
	{
		StringBuilder sBuilder = new StringBuilder();
		int keyLength=keys.length;
		if (keyLength>0)
		{
			if (keys[0].length()>0)
			{
				sBuilder.append("\"");
				sBuilder.append(keys[0].replace((CharSequence)"\"",(CharSequence)"\"\""));
				sBuilder.append("\"");
			}
			
		}
		for (int i=1;i<keys.length;i++)
		{
			sBuilder.append(",");
			if (keys[i].length()>0)
			{
				sBuilder.append("\"");
				sBuilder.append(keys[i].replace((CharSequence)"\"",(CharSequence)"\"\""));
				sBuilder.append("\"");
			}
		}
		
		writer.write(sBuilder.toString());
		writer.newLine();
	}
	
	public static void writeModelStructureToCSV(BufferedWriter writer,String[] keys, String structureLine) throws IOException
	{
		Hashtable<String,String> table=parseToKeyValueMap(structureLine);
		
		StringBuilder sBuilder = new StringBuilder();
		int keyLength=keys.length;
		if (keyLength>0)
		{
			if (table.containsKey(keys[0]))
			{
				sBuilder.append("\"");
				sBuilder.append(table.get(keys[0]).replace((CharSequence)"\"",(CharSequence)"\"\""));
				sBuilder.append("\"");
			}
			
		}
		for (int i=1;i<keys.length;i++)
		{
			sBuilder.append(",");
			if (table.containsKey(keys[i]))
			{
				sBuilder.append("\"");
				sBuilder.append(table.get(keys[i]).replace((CharSequence)"\"",(CharSequence)"\"\""));
				sBuilder.append("\"");
			}
		}
		
		writer.write(sBuilder.toString());
		writer.newLine();
	}
	
	
	
	public static String[] splitCommaDelimitedString(String tokenizedString, char splitChar)
	{
		char[] chars = tokenizedString.toCharArray();
		StringBuilder word= new StringBuilder();
		LinkedList<String> words = new LinkedList<String>();
		
		char currentChar;
		
		
		boolean ignoringSplitToken=false;
		boolean parsingDelimitedQuoteP=false;
		boolean canParseDelimitedQuoteP=false;
		
		int totalChars=chars.length;
		for (int i=0;i<totalChars;i++)
		{
			canParseDelimitedQuoteP=i<totalChars-1;
			currentChar=chars[i];
			
			if (currentChar=='"')
			{
				if (parsingDelimitedQuoteP)
				{
					word.append(currentChar);
					parsingDelimitedQuoteP=false;
				}
				else
				{
					if ((canParseDelimitedQuoteP)&&(chars[i+1]=='"'))
						parsingDelimitedQuoteP=true;
					else
					{
						ignoringSplitToken=!ignoringSplitToken;
					}
				}
			}
			else
			{
				if (currentChar==splitChar)
				{
					if (ignoringSplitToken)
					{
						word.append(currentChar);
					}
					else
					{
						words.add(word.toString());
						word = new StringBuilder();
					}
				}
				else
					word.append(currentChar);
			}
			
		}
		words.add(word.toString());
		return words.toArray(new String[0]);
	}
	
	
	
}
